package com.xiaode.controller.app.statistics;

import cn.hutool.core.bean.BeanUtil;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.MonthStar;
import com.xiaode.common.model.OrgClass;
import com.xiaode.common.model.Student;
import com.xiaode.exce.EnumError;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class StatisticsService {

    /**
     * 积分排名
     */
    public Ret scoreSort(Integer userId, Integer userType, Boolean haveMe) {
        Cache redis = Redis.use();
        Prop use = PropKit.use("testAccount.properties");
        String studentAccount = use.get("studentAccount");
        List<String> strings = Arrays.asList(studentAccount.split(","));
        @SuppressWarnings("unchecked")
		Set<Integer> zrange = redis.zrevrange(Const.user.StudentScore, 0, 19 + strings.size());
        List<Student> students = new ArrayList<>(20 + strings.size());
        for (Integer integer : zrange) {
            Student student = redis.get(Const.user.Student + integer);
            students.add(student);
        }
        students = students.stream().filter(student -> !strings.contains(student.getAccountId().toString())).limit(20).collect(Collectors.toList());
        Kv kv = Kv.by("accountList", strings);
        List<Record> records = Db.template("findStuByAccountList", kv).find();
        ArrayList<Long> list = new ArrayList<>();
        for (Record record : records) {
            list.add(redis.zrevrank(Const.user.StudentScore, record.getInt("id")));
        }
        Ret ret = Ret.ok("scoreSort", students);
        if(haveMe && userType == Const.UserType.student) {
        	//我的排名
	        Long mySort = redis.zrevrank(Const.user.StudentScore, userId);
	        Long finalMySort = mySort;
	        long count = list.stream().filter(aLong -> aLong < finalMySort).count();
	        mySort = mySort - count;
	        //我的积分
	        Student student = redis.get(Const.user.Student + userId);
	        Integer myScore = student.getZScore();
	        ret.set("mySort", mySort).set("myScore", myScore);
        }
        return ret;
    }

    /**
     * 每月之星（年级）
     */
    public Ret monthStar(Integer userId, Integer userType, Date date, Integer gradeId, Boolean haveMe, Integer rankNum) {
    	if(gradeId == null && userType == Const.UserType.student) {
    		Student s = Student.dao.findById(userId);
    		OrgClass oc = OrgClass.dao.findById(s.getClasId());
    		gradeId = oc.getAdminGradeId();
    	}
    	if(gradeId == null) {
    		return Ret.fail().set("error", EnumError.PARAMETER_ERROR.getObj());
    	}
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        int year = localDateTime.getYear();
        int monthValue = localDateTime.getMonthValue();
        if (monthValue < 12) {
            monthValue += 1;
        } else {
            year += 1;
            monthValue = 1;
        }
        Kv kv = Kv.by("yearValue", year).set("monthValue", monthValue).setIfNotNull("rankNum", rankNum);
    	//获取年级下所有班级
    	List<Integer> classIdList = Db.query("SELECT id FROM org_class WHERE adminGradeId = ? AND state = 1", gradeId);
    	if(classIdList.size() > 0) {
        	kv.set("clasIds", classIdList);
        }
        //查询每月之星
        List<Record> list = Db.template("monthStar", kv).find();
        //去除0分
        list = list.stream().filter(record -> record.getInt("score") > 0).collect(Collectors.toList());
        Ret ret = Ret.ok("monthStar", list);
        //我的排名
        if(haveMe != null && haveMe && userType == Const.UserType.student){
        	MonthStar first = MonthStar.dao.findFirst("SELECT id,`rank`,score FROM month_star WHERE studentId = ? AND year(`addTime`) = ? AND month(`addTime`) = ?", userId, year, monthValue);
            Integer rank = 0;
            Integer score = 0;
            if (BeanUtil.isNotEmpty(first)) {
                rank = first.getRank();
                score = first.getScore();
            }
            ret.set("mySort", rank).set("myScore", score);
        }
        return ret;
    }
    
    /**
     * 积分详情（个人页面中统计积分来源）
     */
    public Ret scoreDetails(Integer accountId){
        Record createAccount = Redis.use().hget(Const.user.AccountIdInfo, accountId);
        if(createAccount == null || createAccount.getInt("userType") != Const.UserType.student) {
            return Ret.ok();
        }
        int studentId = createAccount.getInt("id");
    	//运动
    	Integer exerciseMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.TODAY_EXERCISE);
    	//任务
    	Integer ordinaryMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.ORDINARY_TASK);
    	Integer laboruMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.LABORU_TASK);
    	Integer vocationMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.VOCATION_TASK);
    	Integer exampleMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.EXAMPLE_TASK);
    	Integer activityTaskMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.ACTIVITY_PARTAKE);  	
    	//活动
    	Integer activityEMark = Db.queryInt("SELECT IFNULL(SUM(variable),0) FROM mark_log WHERE studentId = ? AND eventType = ?", studentId, Const.addMarkEventType.ACTIVITY);
    	
    	return Ret.ok("exerciseMark", exerciseMark).set("taskMark", ordinaryMark + laboruMark + vocationMark + exampleMark + activityEMark).set("activityEMark", activityTaskMark);
    }
    
    /**
     * 用户月度之星详情
     */
    public Ret monthStarDetails(Integer accountId){
    	
    	Record createAccount = Redis.use().hget(Const.user.AccountIdInfo, accountId);
    	if(createAccount == null || createAccount.getInt("userType") != Const.UserType.student) {
    		return Ret.ok();
    	}
    	int studentId = createAccount.getInt("id");
    	
        LocalDateTime localDateTime = LocalDateTime.now().minusMonths(1);
        LocalDateTime firstTime = localDateTime.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime lastTime = localDateTime.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59);
        
    	//当月 积分
        int scoreCount = Db.queryInt("SELECT IFNULL(SUM(variable), 0) sum FROM mark_log WHERE studentId = ? AND addTime BETWEEN ? AND ?", studentId, firstTime, lastTime);       
    	//教师推荐
        int recommendCount = Db.queryInt("SELECT COUNT(*) count FROM campus_share_teacher_recommend WHERE create_account_id = ? AND add_time BETWEEN ? AND ?", accountId, firstTime, lastTime);
        int recommendMark = recommendCount * 5;
        //发帖/回复
    	int shareCount = Db.queryInt("SELECT COUNT(*) count FROM campus_share_original WHERE user_account_id = ? AND add_time BETWEEN ? AND ?", accountId, firstTime, lastTime);
    	int commentsCount = Db.queryInt("SELECT COUNT(*) count FROM campus_share_comments WHERE create_account_id = ? AND addTime BETWEEN ? AND ?", accountId, firstTime, lastTime);
    	int addMark = (shareCount + commentsCount) * 2;
    	addMark = Math.min(Const.monthMaxMark, addMark);
    	//当月 月度之星分数
    	int zScore = scoreCount + recommendMark + addMark;
    	
    	return Ret.ok("zScore", zScore).set("scoreCount", scoreCount).set("recommendMark", recommendMark).set("addMark", addMark);
    }
    
    
    
}
